package com.atguigu.gmall.order.listener;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Date;
import java.util.Map;

/**
 * @author 李旭
 * @date 2021/12/4 11:07
 * @Description: 关于订单微服务的相关MQ的消息的接收或消费
 */
@Component
@SuppressWarnings("all")
public class OrderInfoListener {


    @Autowired
    private OrderInfoService orderInfoService;
    @Autowired
    private RabbitService rabbitService;

    /**
     * 接收扣减库存的结果
     * @param orderId
     * @param message
     * @param channel
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_WARE_ORDER, durable = "true", autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_WARE_ORDER),
            key = {MqConst.ROUTING_WARE_ORDER}
    ))
    public void receiverMessageDecrStock(String json, Message message, Channel channel) {
        try {
            System.out.println("接收到的消息：" + json);
            Map map = JSONObject.parseObject(json, Map.class);

            if("DEDUCTED".equals(map.get("status"))){
                //扣减成功
                orderInfoService.updateOrderStatus(
                        String.valueOf(map.get("orderId")),ProcessStatus.WAITING_DELEVER);
            }else{
                //库存超卖
                orderInfoService.updateOrderStatus(
                        String.valueOf(map.get("orderId")),ProcessStatus.STOCK_EXCEPTION);
            }

            //手动应答
            //参数1：消息的标识
            //参数2：是否批量应答
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            //   是否投递过  true:已经投递过了本次第二次投递   false:没有投递过 本次是第一次投递
            if (message.getMessageProperties().isRedelivered()) {
                //true:已经投递过了本次第二次投递
                System.out.println("本次是第二次投递了，不能再投递了");
                //拒绝： 将队列中的消息删除 才能让队列中的其它消息继续消费  打日志  转人工
                //参数1：消息的标识
                //参数2:是否放回队列   false：不放回队列（删除）, true:放回队列
                try {
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            } else {
                //false:没有投递过 本次是第一次投递
                System.out.println("没有投递过 本次是第一次投递");
                //参数1：消息的标识
                //参数2：是否批量应答
                //参数2:是否放回队列   false：不放回队列（删除）, true:放回队列
                try {
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                            false, true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }






    /**
     * 接收支付微服务发来的消息  更新订单状态
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_PAYMENT_PAY, durable = "true", autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_PAYMENT_PAY),
            key = {MqConst.ROUTING_PAYMENT_PAY}
    ))
    public void updateOrderStatus(String orderId, Message message, Channel channel) {
        try {
            System.out.println("接收到的消息：" + orderId);
            //更新订单状态
            orderInfoService.updateOrderStatus(orderId, ProcessStatus.PAID);
            //组装仓需要的数据
            Map orderTaskJson = orderInfoService.initWareData(orderId);//组合所需要的数据
            //更新订单状态  通知仓储
            orderInfoService.updateOrderStatus(orderId, ProcessStatus.NOTIFIED_WARE);
            //发消息给库存系统  扣减库存   最终一致性
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK,
                    MqConst.ROUTING_WARE_STOCK, JSONObject.toJSONString(orderTaskJson));
            //手动应答
            //参数1：消息的标识
            //参数2：是否批量应答
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            //   是否投递过  true:已经投递过了本次第二次投递   false:没有投递过 本次是第一次投递
            if (message.getMessageProperties().isRedelivered()) {
                //true:已经投递过了本次第二次投递
                System.out.println("本次是第二次投递了，不能再投递了");
                //拒绝： 将队列中的消息删除 才能让队列中的其它消息继续消费  打日志  转人工
                //参数1：消息的标识
                //参数2:是否放回队列   false：不放回队列（删除）, true:放回队列
                try {
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            } else {
                //false:没有投递过 本次是第一次投递
                System.out.println("没有投递过 本次是第一次投递");
                //参数1：消息的标识
                //参数2：是否批量应答
                //参数2:是否放回队列   false：不放回队列（删除）, true:放回队列
                try {
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                            false, true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }


    /**
     * 基于插件的 消息消费
     *
     * @param orderId
     * @param message
     * @param channel
     */
    @RabbitListener(queues = {MqConst.QUEUE_ORDER_CANCEL})
    public void receiverDelayedMessage(String orderId, Message message, Channel channel) {
        try {
            System.out.println("接收到的消息：" + orderId + ":时间是:" + new Date());
            //处理。。。
            orderInfoService.updateOrderInfoStatus(orderId);
            //手动应答
            //参数1：消息的标识
            //参数2：是否批量应答
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            //   是否投递过  true:已经投递过了本次第二次投递   false:没有投递过 本次是第一次投递
            if (message.getMessageProperties().isRedelivered()) {
                //true:已经投递过了本次第二次投递
                System.out.println("本次是第二次投递了，不能再投递了");
                //拒绝： 将队列中的消息删除 才能让队列中的其它消息继续消费  打日志  转人工
                //参数1：消息的标识
                //参数2:是否放回队列   false：不放回队列（删除）, true:放回队列
                try {
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            } else {
                //false:没有投递过 本次是第一次投递
                System.out.println("没有投递过 本次是第一次投递");
                //参数1：消息的标识
                //参数2：是否批量应答
                //参数2:是否放回队列   false：不放回队列（删除）, true:放回队列
                try {
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                            false, true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }


}
